package com.bandaotixi.cashier.api.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.bandaotixi.cashier.api.common.model.KeyValue;
import com.bandaotixi.cashier.api.common.model.Option;
import com.bandaotixi.cashier.api.common.result.PageResult;
import com.bandaotixi.cashier.api.common.result.Result;
import com.bandaotixi.cashier.api.core.aspect.log.Log;
import com.bandaotixi.cashier.api.core.aspect.log.LogModuleEnum;
import com.bandaotixi.cashier.api.core.mybatis.SqlUtil;
import com.bandaotixi.cashier.api.system.model.entity.User;
import com.bandaotixi.cashier.api.system.model.form.PasswordUpdateForm;
import com.bandaotixi.cashier.api.system.model.form.UserForm;
import com.bandaotixi.cashier.api.system.model.query.UserPageQuery;
import com.bandaotixi.cashier.api.system.model.vo.CurrentUserVO;
import com.bandaotixi.cashier.api.system.model.vo.UserPageVO;
import com.bandaotixi.cashier.api.system.model.vo.UserProfileVO;
import com.bandaotixi.cashier.api.system.service.UserService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.yulichang.query.MPJQueryWrapper;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 用户控制层
 */
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @SaCheckPermission("sys:user")
    @GetMapping("/page")
    public PageResult<UserPageVO> getUserPage(@Valid UserPageQuery queryParams) {
        MPJQueryWrapper<User> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.selectAll(User.class)
                .select("GROUP_CONCAT( r.NAME ) AS roleNames")
                .leftJoin("sys_user_role sur ON u.id = sur.user_id")
                .leftJoin("sys_role r ON sur.role_id = r.id")
                .eq("is_deleted", 0)
                .eq(queryParams.getStatus() != null, "status", queryParams.getStatus())
                .in(!CollectionUtil.isEmpty(queryParams.getRoleIds()), "sur.role_id", queryParams.getRoleIds())
                .like(StringUtils.hasLength(queryParams.getKeywords()), "u.nickname", queryParams.getKeywords())
                .or()
                .like(StringUtils.hasLength(queryParams.getKeywords()), "u.username", queryParams.getKeywords())
                .like(StringUtils.hasLength(queryParams.getKeywords()), "u.mobile", queryParams.getKeywords());
        IPage<UserPageVO> result = userService.selectJoinListPage(queryParams.page(), UserPageVO.class, queryWrapper);
        return PageResult.success(result);
    }

    @SaCheckPermission("sys:user")
    @PostMapping
    @Log(value = "新增用户", module = LogModuleEnum.USER)
    public Result<?> saveUser(@RequestBody @Valid UserForm userForm) {
        boolean result = userService.saveUser(userForm);
        return Result.judge(result);
    }

    @SaCheckPermission("sys:user")
    @GetMapping("/{userId}/form")
    public Result<User> getUserForm(@PathVariable Long userId) {
        User formData = userService.getById(userId);
        return Result.success(formData);
    }

    @SaCheckPermission("sys:user")
    @PutMapping(value = "/{userId}")
    @Log(value = "修改用户", module = LogModuleEnum.USER)
    public Result<Void> updateUser(@PathVariable Long userId, @RequestBody @Valid UserForm userForm) {
        Assert.hasText(userForm.getUsername(), "用户名不能为空");
        // 检查用户名是否存在
        Assert.isTrue(userService.lambdaQuery().eq(User::getUsername, userForm.getUsername()).eq(User::getId, userId).count() == 0, "用户名已存在");
        User user = new User();
        BeanUtils.copyProperties(userForm, user);
        boolean result = userService.updateById(user);
        if (result) {
            SqlUtil.delete("user_role", Map.of("user_id", userId));
            // 修改用户角色
            SqlUtil.relationalBatchUpsert("user_role", "user_id", "role_id", userForm.getRoleIds().stream().map(roleId -> new KeyValue<>(userId, roleId)).toList());
        }
        return Result.judge(result);
    }

    @SaCheckPermission("sys:user")
    @DeleteMapping("/{ids}")
    @Log(value = "删除用户", module = LogModuleEnum.USER)
    public Result<Void> deleteUsers(@PathVariable String ids) {
        List<Long> idList = Arrays.stream(ids.split(",")).map(Long::parseLong).toList();
        Assert.isTrue(!idList.isEmpty(), "请选择要删除的用户");
        boolean result = userService.removeByIds(idList);
        // 删除角色
        SqlUtil.delete("user_role", Map.of("user_id", idList));
        return Result.judge(result);
    }

    @SaCheckPermission("sys:user")
    @PatchMapping(value = "/{userId}/status")
    @Log(value = "修改用户状态", module = LogModuleEnum.USER)
    public Result<Void> updateUserStatus(@PathVariable Long userId, @RequestParam Integer status) {
        boolean result = userService.update(new LambdaUpdateWrapper<User>()
                .eq(User::getId, userId)
                .set(User::getStatus, status)
        );
        return Result.judge(result);
    }

    @GetMapping("/me")
    public Result<CurrentUserVO> getCurrentUser() {
        CurrentUserVO currentUserDTO = userService.getCurrentUser();
        return Result.success(currentUserDTO);
    }

    @GetMapping("/profile")
    public Result<UserProfileVO> getUserProfile() {
        MPJQueryWrapper<User> queryWrapper = new MPJQueryWrapper<>();
        queryWrapper.selectAll(User.class)
                .select("GROUP_CONCAT( r.NAME ) AS roleNames")
                .leftJoin("sys_user_role sur ON u.id = sur.user_id")
                .leftJoin("sys_role r ON sur.role_id = r.id")
                .eq("t.id", StpUtil.getLoginId());
        UserProfileVO userProfile = userService.selectJoinOne(UserProfileVO.class, queryWrapper);
        return Result.success(userProfile);
    }

    @PutMapping("/profile")
    @Log(value = "个人中心修改用户信息", module = LogModuleEnum.USER)
    public Result<?> updateUserProfile(@RequestBody User formData) {
        boolean result = userService.updateById(formData);
        return Result.judge(result);
    }

    @PutMapping(value = "/{userId}/password/reset")
    public Result<?> resetPassword(@PathVariable Long userId, @RequestParam String password) {
        boolean result = userService.lambdaUpdate()
                .eq(User::getId, userId)
                .set(User::getPassword, BCrypt.hashpw(password, BCrypt.gensalt()))
                .update();
        return Result.judge(result);
    }

    @PutMapping(value = "/password")
    public Result<?> changePassword(@RequestBody PasswordUpdateForm data) {
        Long currUserId = StpUtil.getLoginIdAsLong();
        boolean result = userService.changePassword(currUserId, data);
        return Result.judge(result);
    }

    @GetMapping("/options")
    public Result<List<Option<String>>> listUserOptions() {
        List<Option<String>> list = userService.lambdaQuery().list()
                .stream().map(item -> new Option<>(item.getId().toString(), item.getNickname()))
                .toList();
        return Result.success(list);
    }
}
